package com.iplant.aps.serviceImpl;

import com.iplant.aps.service.ASVService;
import com.iplant.aps.service.apsenum.aps.APSSchedulingVersionBPMStatus;
import com.iplant.aps.service.apsenum.aps.APSShiftPeriod;
import com.iplant.aps.service.apsenum.aps.APSTaskStatus;
import com.iplant.aps.service.apsenum.oms.OMSOrderStatus;
import com.iplant.aps.service.po.aps.APSSchedulingVersionBPM;
import com.iplant.aps.service.po.aps.APSTaskPart;
import com.iplant.aps.service.po.aps.APSTaskPartPoint;
import com.iplant.aps.service.po.aps.APSTaskPartPointDay;
import com.iplant.aps.service.po.asv.ASVHandleTask;
import com.iplant.aps.service.po.oms.OMSOrder;
import com.iplant.aps.serviceImpl.dao.APSTaskPartDAO;
import com.iplant.aps.serviceImpl.dao.APSTaskPartPointDAO;
import com.iplant.aps.serviceImpl.dao.aps.APSSchedulingVersionBPMDAO;
import com.iplant.aps.serviceImpl.dao.aps.APSTaskPartPointDayDAO;
import com.iplant.aps.serviceImpl.dao.oms.OMSOrderDAO;
import com.iplant.base.po.OutResult;
import com.iplant.base.po.Pagination;
import com.iplant.base.po.ServiceResult;
import com.iplant.base.po.enums.ExceptionTypes;
import com.iplant.base.utils.general.LockHelper;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.base.utils.serializer.CloneTool;
import com.iplant.base.utils.sql.orm.ORMUtils;
import com.iplant.base.utils.sql.orm.PoService;
import com.iplant.base.utils.tasker.TaskTimerUtils;
import com.iplant.basic.service.basicenum.bpm.BPMEventModule;
import com.iplant.basic.service.basicenum.bpm.BPMTaskStatus;
import com.iplant.basic.service.basicenum.bpm.TaskQueryType;
import com.iplant.basic.service.po.bms.BMSEmployee;
import com.iplant.basic.utils.Constants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ASVServiceImpl implements ASVService {

    //region 构造函数
    public ASVServiceImpl() {
        Constants.BPMServiceMap.put(BPMEventModule.MONTH_PLAN_AUDIT, this);
        Constants.BPMServiceMap.put(BPMEventModule.WEEK_PLAN_AUDIT, this);
    }

    //endregion

    private static final LockHelper mLockHelper = LockHelper.getLock(ASVServiceImpl.class);

    //region 单实例

    private static volatile ASVService Instance = null;


    static {
        TaskTimerUtils.AddTask(() -> {


            ASVHandleTask wASVHandleTask = mHandleTaskResource.get();
            if (wASVHandleTask == null)
                return;

            ServiceResult<Integer> wServiceResult = getInstance().ASV_SaveScheduleResult(wASVHandleTask.LoginUser,
                    wASVHandleTask.TaskPartList);


            if (StringUtils.isNotEmpty(wServiceResult.FaultCode)) {
                log.info("TaskTimerUtils SaveScheduleResult Error:{}", wServiceResult.FaultCode);
            }
        }, 2000, -1);
    }

    public static ASVService getInstance() {


        if (Instance == null) {
            synchronized (mLockHelper) {
                if (Instance == null) {
                    Instance = new ASVServiceImpl();

                }
            }
        }

        return Instance;
    }


    //endregion

    //region POService
    private PoService<APSTaskPart> mAPSTaskPartService = ORMUtils.GetPoService(APSTaskPart.class);
    private PoService<APSTaskPartPoint> mAPSTaskPartPointService = ORMUtils.GetPoService(APSTaskPartPoint.class);
    //endregion

    //region 流程
    @Override
    public ServiceResult<APSSchedulingVersionBPM> BPM_QueryDefaultTask(BMSEmployee wLoginUser,
                                                                       int wTaskID, int wEventID) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSSchedulingVersionBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);


            int wAPSShiftPeriod = 0;
            if (wEventID == BPMEventModule.MONTH_PLAN_AUDIT.getValue()) {
                wAPSShiftPeriod = APSShiftPeriod.Month.getValue();
            } else if (wEventID == BPMEventModule.WEEK_PLAN_AUDIT.getValue()) {
                wAPSShiftPeriod = APSShiftPeriod.Week.getValue();
            }

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("APSShiftPeriod", wAPSShiftPeriod);
            wParams.put("Active", 1);
            wParams.put("Status", APSSchedulingVersionBPMStatus.Saved.getValue());

            APSSchedulingVersionBPM wAPSSchedulingVersionBPM =
                    APSSchedulingVersionBPMDAO.getInstance().SelectPO(wLoginUser,
                            wParams, wErrorCode);

            if (wErrorCode.Result != 0) {
                wResult.AddFaultCode(wErrorCode);
                return wResult;
            }
            if (wAPSSchedulingVersionBPM == null || wAPSSchedulingVersionBPM.ID <= 0) {

                wResult.FaultCode += "提示：计划未排程!";
                return wResult;
            }

            wAPSSchedulingVersionBPM.FlowType = wEventID;
            wAPSSchedulingVersionBPM.UpFlowID = wLoginUser.ID;
            wAPSSchedulingVersionBPM.UpFlowName = wLoginUser.Name;
            if (wAPSSchedulingVersionBPM.TaskPartIDList != null && wAPSSchedulingVersionBPM.TaskPartIDList.size() > 0) {
                wParams = new HashMap<>();
                wAPSSchedulingVersionBPM.TaskPartList = APSTaskPartDAO.getInstance().SelectPOList(wLoginUser,
                        wAPSSchedulingVersionBPM.TaskPartIDList, wParams, APSTaskPart.class, Pagination.getMaxSize(),
                        wErrorCode);
                wAPSSchedulingVersionBPM.TaskPartList.sort(Comparator.comparing(APSTaskPart::getRoutePartOrder));
            }

            wResult.Result = wAPSSchedulingVersionBPM;

        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSSchedulingVersionBPM> BPM_CreateTask(BMSEmployee wLoginUser,
                                                                 BPMEventModule wEventID) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSSchedulingVersionBPM();
        wResult.FaultCode += "流程不支持直接创建！";
        return wResult;
    }

    @Override
    public ServiceResult<APSSchedulingVersionBPM> BPM_SubmitTask(BMSEmployee wLoginUser,
                                                                 APSSchedulingVersionBPM wData) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wData.EditorID = wLoginUser.ID;
            wData.EditTime = Calendar.getInstance();

            if (wData.Status == APSSchedulingVersionBPMStatus.Confirm.getValue()) {
                wData.StatusText = "已审批";

                Map<String, Object> wParams = new HashMap<String, Object>();
                List<APSTaskPart> wAPSTaskPartList = APSTaskPartDAO.getInstance().SelectPOList(wLoginUser,
                        wData.TaskPartIDList, wParams, APSTaskPart.class, Pagination.getMaxSize(), wErrorCode);

                if (wData.APSShiftPeriod == APSShiftPeriod.Month.getValue()) {
                    //子项状态维护为"已下达"
                    for (APSTaskPart wAPSTaskPart : wAPSTaskPartList) {
                        wAPSTaskPart.Status = APSTaskStatus.Issued.getValue();
                        wAPSTaskPart.EditorID = wLoginUser.ID;
                        wAPSTaskPart.EditTime = Calendar.getInstance();
                    }
                    APSTaskPartDAO.getInstance().UpdatePoList(wLoginUser, wAPSTaskPartList, wErrorCode);

                    //生成物料需求计划
                    Calendar wStartDate =
                            wAPSTaskPartList.stream().min(Comparator.comparing(APSTaskPart::getPartStartTime)).get().PartStartTime;
                    Calendar wEndDate =
                            wAPSTaskPartList.stream().max(Comparator.comparing(APSTaskPart::getPartEndTime)).get().PartEndTime;
                    MRPServiceImpl.getInstance().MRP_CreateMaterialPlan(wLoginUser, wStartDate, wEndDate);
                } else {
                    //非当前版本禁用；
                    APS_DisableWeekPlan(wLoginUser, wAPSTaskPartList, wErrorCode);
                    //触发周计划下达逻辑，复制一版当前版本
                    TaskTimerUtils.AddTask("APS_WeekPlanIssueLogic",
                            () -> APS_WeekPlanIssueLogic(wLoginUser, wAPSTaskPartList, wErrorCode)
                    );
                    //周计划下达后，批量更新订单状态为`计划就绪`
                    List<Integer> wOrderIDList =
                            wAPSTaskPartList.stream().map(p -> p.OrderID).distinct().collect(Collectors.toList());
                    wParams.clear();
                    List<OMSOrder> wOMSOrderList = OMSOrderDAO.getInstance().SelectPOList(wLoginUser, wOrderIDList,
                            wParams, OMSOrder.class,
                            Pagination.getNewMaxSize(),
                            wErrorCode);
                    if (wOMSOrderList != null && wOMSOrderList.size() > 0) {
                        for (OMSOrder wOMSOrder : wOMSOrderList) {
                            if (wOMSOrder.Status == OMSOrderStatus.ProductReady.getValue()) {
                                wOMSOrder.setUserInfo(wLoginUser);
                                wOMSOrder.Status = OMSOrderStatus.PlanReady.getValue();
                            }
                        }
                        OMSOrderDAO.getInstance().UpdatePoList(wLoginUser, wOMSOrderList, wErrorCode);
                    }
                }
            }

            //若撤销，则禁用计划
            if (wData.Status == BPMTaskStatus.Canceled.getValue()) {
                wData.StatusText = "已驳回";
                Map<String, Object> wParams = new HashMap<String, Object>();
                List<APSTaskPart> wAPSTaskPartList = APSTaskPartDAO.getInstance().SelectPOList(wLoginUser,
                        wData.TaskPartIDList, wParams, APSTaskPart.class, Pagination.getMaxSize(), wErrorCode);
                for (APSTaskPart wAPSTaskPart : wAPSTaskPartList) {
                    wAPSTaskPart.setUserInfo(wLoginUser);
                    wAPSTaskPart.Active = 2;
                    wAPSTaskPart.EditorID = wLoginUser.ID;
                    wAPSTaskPart.EditTime = Calendar.getInstance();
                }
                APSTaskPartDAO.getInstance().UpdatePoList(wLoginUser, wAPSTaskPartList, wErrorCode);
            } else if (wData.Status == BPMTaskStatus.Rejected.getValue()) {
                wData.StatusText = "已撤销";
                Map<String, Object> wParams = new HashMap<String, Object>();
                List<APSTaskPart> wAPSTaskPartList = APSTaskPartDAO.getInstance().SelectPOList(wLoginUser,
                        wData.TaskPartIDList, wParams, APSTaskPart.class, Pagination.getMaxSize(), wErrorCode);
                for (APSTaskPart wAPSTaskPart : wAPSTaskPartList) {
                    wAPSTaskPart.setUserInfo(wLoginUser);
                    wAPSTaskPart.Active = 2;
                    wAPSTaskPart.EditorID = wLoginUser.ID;
                    wAPSTaskPart.EditTime = Calendar.getInstance();
                }
                APSTaskPartDAO.getInstance().UpdatePoList(wLoginUser, wAPSTaskPartList, wErrorCode);
            }

            APSSchedulingVersionBPMDAO.getInstance().UpdatePo(wLoginUser, wData, wErrorCode);
            wResult.Result = wData;

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    /**
     * 禁用版本计划
     */
    private void APS_DisableWeekPlan(BMSEmployee wLoginUser, List<APSTaskPart> wAPSTaskPartList,
                                     OutResult<Integer> wErrorCode) {
        try {
            if (wAPSTaskPartList == null || wAPSTaskPartList.size() <= 0) {
                return;
            }

            for (APSTaskPart wAPSTaskPart : wAPSTaskPartList) {
                wAPSTaskPart.Active = 2;
                wAPSTaskPart.Status = APSTaskStatus.Issued.getValue();
                wAPSTaskPart.setUserInfo(wLoginUser);
            }
            mAPSTaskPartService.UpdatePoList(wLoginUser, wAPSTaskPartList, wErrorCode);

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("TaskPartID", StringUtils.Join(",",
                    wAPSTaskPartList.stream().map(p -> p.ID).collect(Collectors.toList())));
            List<APSTaskPartPoint> wAPSTaskPartPointList =
                    APSTaskPartPointDAO.getInstance().SelectPOList(wLoginUser,
                            wParams,
                            Pagination.getMaxSize(), wErrorCode);

            for (APSTaskPartPoint wAPSTaskPartPoint : wAPSTaskPartPointList) {
                wAPSTaskPartPoint.Status = APSTaskStatus.Issued.getValue();
                wAPSTaskPartPoint.Active = 2;
                wAPSTaskPartPoint.setUserInfo(wLoginUser);
            }
            mAPSTaskPartPointService.UpdatePoList(wLoginUser, wAPSTaskPartPointList, wErrorCode);
        } catch (Exception ex) {
            log.error("APS_DisableWeekPlan", ex);
        }
    }

    /**
     * 周计划下达逻辑
     */
    private void APS_WeekPlanIssueLogic(BMSEmployee wLoginUser, List<APSTaskPart> wAPSTaskPartList,
                                        OutResult<Integer> wErrorCode) {
        try {
            if (wAPSTaskPartList == null || wAPSTaskPartList.size() <= 0) {
                return;
            }

            //工艺复制
            List<APSTaskPart> wNewTaskPartList = new ArrayList<>();
            for (APSTaskPart wAPSTaskPart : wAPSTaskPartList) {
                APSTaskPart wCloneTask = CloneTool.Clone(wAPSTaskPart, APSTaskPart.class);
                Map<String, Object> wParams = new HashMap<String, Object>();
                wParams.put("OrderID", wAPSTaskPart.OrderID);
                wParams.put("RoutePartID", wAPSTaskPart.RoutePartID);
                wParams.put("IsCurrent", 1);
                APSTaskPart wHisTask = mAPSTaskPartService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (wHisTask != null && wHisTask.ID > 0) {
                    wCloneTask.ID = wHisTask.ID;
                    wCloneTask.Code = wHisTask.Code;
                    wCloneTask.Active = 1;
                    wCloneTask.IsCurrent = 1;
                } else {
                    wCloneTask.Code = "";
                    wCloneTask.ID = 0;
                    wCloneTask.IsCurrent = 1;
                    wCloneTask.Active = 1;
                    wCloneTask.Status = APSTaskStatus.Issued.getValue();
                }
                wCloneTask.setUserInfo(wLoginUser);
                wNewTaskPartList.add(wCloneTask);
            }
            mAPSTaskPartService.UpdatePoList(wLoginUser, wNewTaskPartList, wErrorCode);

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("TaskPartID", StringUtils.Join(",",
                    wAPSTaskPartList.stream().map(p -> p.ID).collect(Collectors.toList())));
            List<APSTaskPartPoint> wAPSTaskPartPointList =
                    APSTaskPartPointDAO.getInstance().SelectPOList(wLoginUser,
                            wParams,
                            Pagination.getMaxSize(), wErrorCode);

            List<APSTaskPartPoint> wNewTaskPartPointList = new ArrayList<>();
            for (APSTaskPartPoint wAPSTaskPartPoint : wAPSTaskPartPointList) {
                APSTaskPartPoint wPartPointClone = CloneTool.Clone(wAPSTaskPartPoint, APSTaskPartPoint.class);
                wParams.clear();
                wParams.put("OrderID", wAPSTaskPartPoint.OrderID);
                wParams.put("RoutePartID", wAPSTaskPartPoint.RoutePartID);
                wParams.put("RoutePartPointID", wAPSTaskPartPoint.RoutePartPointID);
                wParams.put("IsCurrent", 1);
                APSTaskPartPoint wHisPartPoint = mAPSTaskPartPointService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (wHisPartPoint != null && wHisPartPoint.ID > 0) {
                    wPartPointClone.ID = wHisPartPoint.ID;
                    wPartPointClone.Code = wHisPartPoint.Code;
                    wPartPointClone.Active = 1;
                } else {
                    wPartPointClone.ID = 0;
                    wPartPointClone.Code = "";
                    wPartPointClone.IsCurrent = 1;
                    wPartPointClone.Active = 1;
                    wPartPointClone.Status = APSTaskStatus.Issued.getValue();
                }
                wPartPointClone.TaskPartID =
                        wNewTaskPartList.stream().filter(p -> p.OrderID == wAPSTaskPartPoint.OrderID
                                && p.RoutePartID == wAPSTaskPartPoint.RoutePartID).findFirst().get().ID;
                wPartPointClone.setUserInfo(wLoginUser);
                wNewTaskPartPointList.add(wPartPointClone);
            }
            mAPSTaskPartPointService.UpdatePoList(wLoginUser, wNewTaskPartPointList, wErrorCode);
        } catch (Exception ex) {
            log.error("APS_WeekPlanIssueLogic", ex);
        }
    }

    @Override
    public ServiceResult<APSSchedulingVersionBPM> BPM_GetTask(BMSEmployee wLoginUser, int wID) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSSchedulingVersionBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("ID", wID);

            wResult.Result = APSSchedulingVersionBPMDAO.getInstance().SelectPO(wLoginUser, wParams, wErrorCode);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public Class<APSSchedulingVersionBPM> GetTClass() {
        return APSSchedulingVersionBPM.class;
    }

    @Override
    public ServiceResult<List<APSSchedulingVersionBPM>> BPM_QueryEmployeeAllWeb(BMSEmployee wLoginUser, Map<String,
            Object> wParams, Pagination wPagination) {
        ServiceResult<List<APSSchedulingVersionBPM>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            int wStatus = StringUtils.parseInt(wParams.get("Status"));
            int wAPSShiftPeriod = StringUtils.parseInt(wParams.get("APSShiftPeriod"));
            switch (wStatus) {
                case 0://待办
                    wParams.remove("CStartTime");
                    wParams.remove("CEndTime");
                    wParams.remove("DStartTime");
                    wParams.remove("DEndTime");
                    wParams.put("Status", "2,3,4,5,6,7");
                    wResult.Result = APSSchedulingVersionBPMDAO.getInstance().SelectPOList(wLoginUser, wParams,
                            wPagination,
                            wErrorCode);
                    break;
                case 1://已办
                    wParams.put("Status", "20,21,22");
                    wResult.Result = APSSchedulingVersionBPMDAO.getInstance().SelectPOList(wLoginUser, wParams,
                            wPagination,
                            wErrorCode);
                    break;
                default://全部
                    wParams.put("Status", "2,3,4,5,6,7,20,21,22");
                    wResult.Result = APSSchedulingVersionBPMDAO.getInstance().SelectPOList(wLoginUser, wParams,
                            wPagination,
                            wErrorCode);
                    break;
            }

            if (wResult.Result.size() == 0 || wStatus == 1) {
                return wResult;
            }

            int wBPMEventModule = 0;
            if (wAPSShiftPeriod == APSShiftPeriod.Week.getValue()) {
                wBPMEventModule = BPMEventModule.WEEK_PLAN_AUDIT.getValue();
            } else if (wAPSShiftPeriod == APSShiftPeriod.Month.getValue()) {
                wBPMEventModule = BPMEventModule.MONTH_PLAN_AUDIT.getValue();
            }

            // 待办数据处理
            List<APSSchedulingVersionBPM> wBaseList =
                    APSSchedulingVersionBPMDAO.getInstance().BFC_GetUndoTaskList(wLoginUser,
                            wLoginUser.ID,
                            new ArrayList<>(Collections.singletonList(wBPMEventModule))
                            , wParams, wPagination, wErrorCode);
            if (wBaseList == null || wBaseList.size() == 0) {
                return wResult;
            }
            for (APSSchedulingVersionBPM wTaskBase : wBaseList) {
                wTaskBase.TagTypes = TaskQueryType.ToHandle.getValue();
                for (int i = 0; i < wResult.Result.size(); i++) {
                    if (wResult.Result.get(i).ID == wTaskBase.ID)
                        wResult.Result.set(i, wTaskBase);
                }
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }
    //endregion

    @Override
    public ServiceResult<Integer> APS_SaveSchedulingVersion(BMSEmployee wLoginUser, List<APSTaskPart> wTaskPartList,
                                                            int wAPSShiftPeriod) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①查询是否还有未审批的月/周计划，若有，提示审批完再排程
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("APSShiftPeriod", wAPSShiftPeriod);
            wParams.put("Status", "2,3,4,5,6,7,8,9,10");
            wParams.put("Active", 1);
            APSSchedulingVersionBPM wAPSSchedulingVersionBPM =
                    APSSchedulingVersionBPMDAO.getInstance().SelectPO(wLoginUser,
                            wParams, wErrorCode);

            wResult.AddFaultCode(wErrorCode);

            if (wAPSSchedulingVersionBPM != null && wAPSSchedulingVersionBPM.ID > 0) {
                wResult.FaultCode += StringUtils.Format("系统存在未审批完的{0}计划，请先审批完再操作!",
                        APSShiftPeriod.getEnumType(wAPSShiftPeriod).getLabel());
                return wResult;
            }
            //②禁用保存状态的月/周计划排程版本
            wParams = new HashMap<String, Object>();
            wParams.put("APSShiftPeriod", wAPSShiftPeriod);
            wParams.put("Status", "1");
            wParams.put("Active", 1);
            List<APSSchedulingVersionBPM> wAPSSchedulingVersionBPMList =
                    APSSchedulingVersionBPMDAO.getInstance().SelectPOList(wLoginUser, wParams, Pagination.getMaxSize(),
                            wErrorCode);

            wResult.AddFaultCode(wErrorCode);

            for (APSSchedulingVersionBPM wItem : wAPSSchedulingVersionBPMList) {
                wItem.Active = 2;
                wItem.EditorID = wLoginUser.ID;
                wItem.EditTime = Calendar.getInstance();
                APSSchedulingVersionBPMDAO.getInstance().UpdatePo(wLoginUser, wItem, wErrorCode);
                wResult.AddFaultCode(wErrorCode);
            }
            //保存排程结果
            mHandleTaskResource.add(new ASVHandleTask(wLoginUser, wTaskPartList));

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<APSSchedulingVersionBPM> APS_QuerySchedulingVersionBPMInfo(BMSEmployee wLoginUser,
                                                                                    Map<String, Object> wParams) {
        ServiceResult<APSSchedulingVersionBPM> wResult = new ServiceResult<>();
        wResult.Result = new APSSchedulingVersionBPM();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = APSSchedulingVersionBPMDAO.getInstance().SelectPO(wLoginUser, wParams, wErrorCode);
            if (wResult.Result != null && wResult.Result.ID > 0 && wResult.Result.TaskPartIDList != null
                    && wResult.Result.TaskPartIDList.size() > 0) {
                wParams = new HashMap<>();
                wResult.Result.TaskPartList = APSTaskPartDAO.getInstance().SelectPOList(wLoginUser,
                        wResult.Result.TaskPartIDList, wParams, APSTaskPart.class, Pagination.getMaxSize(), wErrorCode);
                // 排序
                wResult.Result.TaskPartList.sort(Comparator.comparing(APSTaskPart::getRoutePartOrder));
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    /**
     * 保存排程结果
     */
    @Override
    public synchronized ServiceResult<Integer> ASV_SaveScheduleResult(BMSEmployee wLoginUser,
                                                                      List<APSTaskPart> wTaskPartList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        OutResult<Integer> wErrorCode = new OutResult<>(0);
        try {
            //③保存明细
            for (APSTaskPart wAPSTaskPart : wTaskPartList) {
                //禁用同订单、同工艺、同工序、同排程性质的工位计划（封装函数）
                DisableSamePlan(wLoginUser, wAPSTaskPart, wErrorCode);
                if (wErrorCode.Result != 0) {
                    wResult.AddFaultCode(wErrorCode);
                    continue;
                }


                wAPSTaskPart.Status = APSTaskStatus.Saved.getValue();
                wAPSTaskPart.Active = 1;
                wAPSTaskPart.CreatorID = wLoginUser.ID;
                wAPSTaskPart.CreateTime = Calendar.getInstance();
                wAPSTaskPart.EditorID = wLoginUser.ID;
                wAPSTaskPart.EditTime = Calendar.getInstance();
                APSTaskPartDAO.getInstance().UpdatePo(wLoginUser, wAPSTaskPart, wErrorCode);

                if (wErrorCode.Result != 0) {
                    wResult.AddFaultCode(wErrorCode);
                    continue;
                }
                //保存工序计划
                for (APSTaskPartPoint wAPSTaskPartPoint : wAPSTaskPart.TaskPartPointList) {
                    wAPSTaskPartPoint.CreatorID = wLoginUser.ID;
                    wAPSTaskPartPoint.EditorID = wLoginUser.ID;
                    wAPSTaskPartPoint.EditTime = Calendar.getInstance();
                    wAPSTaskPartPoint.Active = 1;
                    wAPSTaskPartPoint.Status = APSTaskStatus.Saved.getValue();
                    wAPSTaskPartPoint.TaskPartID = wAPSTaskPart.ID;
                    APSTaskPartPointDAO.getInstance().UpdatePo(wLoginUser, wAPSTaskPartPoint, wErrorCode);

                    if (wErrorCode.Result != 0) {
                        wResult.AddFaultCode(wErrorCode);
                        continue;
                    }
                    //保存日计划
                    APSTaskPartPointDayDAO.getInstance().APS_SaveDayPlan(wLoginUser, wAPSTaskPart, wAPSTaskPartPoint,
                            wErrorCode);
                    if (wErrorCode.Result != 0) {
                        wResult.AddFaultCode(wErrorCode);
                    }
                }

                if (StringUtils.isNotEmpty(wResult.FaultCode))
                    break;
            }

            if (StringUtils.isNotEmpty(wResult.FaultCode))
                return wResult;

            //②创建排程版本
            APSSchedulingVersionBPM wNewVersionBPM = new APSSchedulingVersionBPM();
            wNewVersionBPM.Active = 1;
            wNewVersionBPM.Status = APSSchedulingVersionBPMStatus.Saved.getValue();
            wNewVersionBPM.APSShiftPeriod = wTaskPartList.get(0).ShiftPeriod;
            wNewVersionBPM.TaskPartIDList =
                    wTaskPartList.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
            wNewVersionBPM.CreatorID = wLoginUser.ID;
            wNewVersionBPM.CreateTime = Calendar.getInstance();
            wNewVersionBPM.EditorID = wLoginUser.ID;
            wNewVersionBPM.EditTime = Calendar.getInstance();
            APSSchedulingVersionBPMDAO.getInstance().UpdatePo(wLoginUser, wNewVersionBPM, wErrorCode);

            wResult.AddFaultCode(wErrorCode);
        } catch (Exception ex) {
            wResult.FaultCode += ex.getMessage();
            log.error("SaveScheduleResult", ex);
        }
        return wResult;
    }

    /**
     * 禁用同订单、同工艺、同工序、同排程性质的工位计划
     */
    private void DisableSamePlan(BMSEmployee wLoginUser, APSTaskPart wAPSTaskPart, OutResult<Integer> wErrorCode) {
        try {
            //①查询同订单、同工艺、同排程性质的工位计划
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("OrderID", wAPSTaskPart.OrderID);
            wParams.put("RoutePartID", wAPSTaskPart.RoutePartID);
            wParams.put("ShiftPeriod", wAPSTaskPart.ShiftPeriod);
            wParams.put("Active", 1);
            List<APSTaskPart> wAPSTaskPartList = APSTaskPartDAO.getInstance().SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            if (wAPSTaskPartList == null || wAPSTaskPartList.size() == 0) {
                return;
            }
            //②禁用工位计划
            for (APSTaskPart wItem : wAPSTaskPartList) {
                wItem.setUserInfo(wLoginUser);
                wItem.Active = 2;
                APSTaskPartDAO.getInstance().UpdatePo(wLoginUser, wItem, wErrorCode);
                //③查询工序计划
                wParams.clear();
                wParams.put("TaskPartID", wItem.ID);
                wParams.put("Active", 1);
                List<APSTaskPartPoint> wAPSTaskPartPointList =
                        APSTaskPartPointDAO.getInstance().SelectPOList(wLoginUser,
                                wParams,
                                Pagination.getNewMaxSize(), wErrorCode);
                //④禁用工序计划
                if (wAPSTaskPartPointList != null && wAPSTaskPartPointList.size() > 0) {
                    for (APSTaskPartPoint wAPSTaskPartPoint : wAPSTaskPartPointList) {
                        wAPSTaskPartPoint.setUserInfo(wLoginUser);
                        wAPSTaskPartPoint.Active = 2;
                        APSTaskPartPointDAO.getInstance().UpdatePo(wLoginUser, wAPSTaskPartPoint, wErrorCode);
                    }
                }
                //⑤查询日计划
                List<APSTaskPartPointDay> wAPSTaskPartPointDayList =
                        APSTaskPartPointDayDAO.getInstance().SelectPOList(wLoginUser, wParams,
                                Pagination.getNewMaxSize(),
                                wErrorCode);
                //⑥禁用日计划
                if (wAPSTaskPartPointDayList != null && wAPSTaskPartPointDayList.size() > 0) {
                    for (APSTaskPartPointDay wAPSTaskPartPointDay : wAPSTaskPartPointDayList) {
                        wAPSTaskPartPointDay.setUserInfo(wLoginUser);
                        wAPSTaskPartPointDay.Active = 2;
                        APSTaskPartPointDayDAO.getInstance().UpdatePo(wLoginUser, wAPSTaskPartPointDay, wErrorCode);
                    }
                }
                //⑦查询/禁用派工计划
                APSTaskPartDAO.getInstance().APS_DisableTaskSelf(wLoginUser, wItem.ID, wErrorCode);
            }
        } catch (Exception ex) {
            log.error("getDBSQL", ex);
        }
    }
}
